package handler

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"lib/http"
	"lib/id"
	"lib/structs/enum"
	"lib/structs/lms"
	"lib/structs/tables"
	"lib/utils"
	"lms/repository"
	"lms/service"
	"os"
	"path/filepath"
	"time"
)

type coursewareApi struct {
}

var CoursewareApi = coursewareApi{}

func (a coursewareApi) Upload(c *gin.Context) {
	f, err := c.FormFile("file")
	if err != nil {
		http.BadWithParamsError(c)
		return
	}
	filename := fmt.Sprintf("%d_%s", id.GetSnowId(), f.Filename)
	err = c.SaveUploadedFile(f, filepath.Join(enum.FilePath.CoursewareFolder, filename))
	if err != nil {
		http.BadWithCode(c, enum.ErrorMap.CoursewareFileUploadFail)
		return
	}
	http.Ok(c, filename)
}

func (a coursewareApi) CreateCoursewareFolder(c *gin.Context) {
	var in lms.AddCourseFolder
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	err, b := repository.CoursewareDb.FindCoursewareByName(in.Name, in.ParentId)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	if b {
		http.BadWithCode(c, enum.ErrorMap.CoursewareNameExist)
		return
	}
	self := http.GetCurrentUser(c)
	m := &tables.CoursewareFolder{
		FolderId: id.GetSnowId(),
		Name:     in.Name,
		Describe: in.Describe,
		ParentId: in.ParentId,
		Sort:     in.Sort,
		AutoCreateInfo: tables.AutoCreateInfo{
			Creator:   self.Nickname,
			CreatorId: self.UserID,
			CreatedAt: time.Now().Unix(),
			UpdatedAt: 0,
			DeletedAt: 0,
		},
	}
	if err := repository.CoursewareDb.CreateCoursewareFolder(m); err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (a coursewareApi) DeleteFolder(c *gin.Context) {
	in := struct {
		Id int64 `uri:"id"`
	}{}
	if err := c.ShouldBindUri(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	if in.Id == 1 {
		http.BadWithCode(c, enum.ErrorMap.SysDateNoDelete)
		return
	}
	err := repository.CoursewareDb.DeleteFolder(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (a coursewareApi) GetCoursewareCode(c *gin.Context) {
	code, err := service.CoursewareService.GetCode()
	if err != nil {
		http.BadWithCode(c, enum.ErrorMap.GettingCoursewareErr)
		return
	}
	http.Ok(c, code)
}

func (a coursewareApi) Create(c *gin.Context) {
	var in lms.AddCourseware
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	self := http.GetCurrentUser(c)
	fp := filepath.Join(enum.FilePath.CoursewareFolder, in.FileUid)
	m := &tables.Courseware{
		Id:                 id.GetSnowId(),
		Code:               in.Code,
		Name:               in.FileName,
		FileKind:           service.CoursewareService.GetFileKind(utils.GetFileSuffix(in.FileName)),
		FilePath:           fp,
		FileSize:           utils.GetFileSize(fp),
		MD5:                utils.GetFileMD5(fp),
		With:               in.Width,
		Height:             in.Height,
		ExtensionName:      utils.GetFileSuffix(in.FileName),
		Label:              in.Label,
		CoursewareFolderId: in.CoursewareFolderId,
		AllowDownload:      in.AllowDownload,
		IsPublic:           in.IsPublic,
		VectorStatus:       enum.FileVectorStatus.Init,
		AutoCreateInfo: tables.AutoCreateInfo{
			Creator:   self.Nickname,
			CreatorId: self.UserID,
			CreatedAt: time.Now().Unix(),
			UpdatedAt: 0,
			DeletedAt: 0,
		},
	}
	if err := repository.CoursewareDb.Save(m); err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
	return
}

func (a coursewareApi) Update(c *gin.Context) {
	var in lms.UpdateCourseware
	if err := c.ShouldBindJSON(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	d, err := repository.CoursewareDb.FindById(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	self := http.GetCurrentUser(c)
	if self.UserID != d.CreatorId {
		http.BadWithCode(c, enum.ErrorMap.AccessDeniedForCreate)
		return
	}
	d.Name = in.FileName
	d.Code = in.Code
	d.IsPublic = in.IsPublic
	d.AllowDownload = in.AllowDownload
	d.Label = in.Label
	d.CoursewareFolderId = in.CoursewareFolderId
	if err = repository.CoursewareDb.Save(&d); err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OK204(c)
}

func (a coursewareApi) Delete(c *gin.Context) {
	in := struct {
		Id int64 `uri:"id"`
	}{}
	if err := c.ShouldBindUri(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	d, err := repository.CoursewareDb.FindById(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	self := http.GetCurrentUser(c)
	if self.UserID != d.CreatorId {
		http.BadWithCode(c, enum.ErrorMap.AccessDeniedForCreate)
		return
	}
	err = repository.CoursewareDb.DeleteById(in.Id)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	err = os.Remove(d.FilePath)
	if err != nil {
		http.BadWithCode(c, enum.ErrorMap.DeleteFileErr)
		return
	}
	http.OK204(c)
}

func (a coursewareApi) GetAllFolder(c *gin.Context) {
	li, err := repository.CoursewareDb.FindAllCoursewareFolder()
	if err != nil {
		http.BadWithDB(c, err)
	}
	http.Ok(c, li)
}

func (a coursewareApi) Page(c *gin.Context) {
	var in lms.SearchCourseware
	if err := c.ShouldBindQuery(&in); err != nil {
		http.BadWithParamsError(c)
		return
	}
	ids, err := service.CoursewareService.GetSubCoursewareFolderIds(in.FolderId)
	if err != nil {
		http.BadWithCode(c, enum.ErrorMap.UnknownError)
		return
	}
	self := http.GetCurrentUser(c)
	li, total, err := repository.CoursewareDb.FindPage(in, ids, self.UserID)
	if err != nil {
		http.BadWithDB(c, err)
		return
	}
	http.OkPage(c, li, total)
}
